home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
man.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
18KB
|
733 lines
/* man - display and manage manual pages Author: Dick van Veen */
/* Options:
* man <ar-dir>? <ar-name>? <man-page>+
* display <man-page> from <ar-name> in <ar-dir>.
* man <ar-dir>? <ar-name>?
* display contents of <ar-name> in <ar-dir>,
* by using the <cursor-keys> and <return> a page is choosen.
*
* <ar-dir> is a directory name starting with a '/'.
* the default directory is '/usr/man'.
*
* <ar-name> is a digit, when no digit is used, chapter 1 searched.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include <termcap.h>
#include <stdio.h>
#ifndef INDEX_H
#define INDEX_H
#define MAN_DELIM '#'
#define NAME_SIZE 12 /* for size in index file */
#define NAME_WIDTH 15 /* for on screen projection */
#define AR_NAME_SIZE 64 /* for file names */
#define AR_DIR "/usr/man"
#define AR_NAME "/man"
#define AR_INDEX "/._man"
struct INDEX {
long page_pos; /* position in index file */
char page_name[NAME_SIZE]; /* name of manual page */
};
extern char ar_name[AR_NAME_SIZE]; /* name of man archive file */
extern char ar_index[AR_NAME_SIZE]; /* name of index file */
extern struct INDEX *index_buf; /* contains indices */
extern int max_index_nr; /* number of indices in index_buf */
/* Should be a prototype */
extern void read_index();
#endif
#ifndef DISPLAY_H
#define DISPLAY_H
#define MAX_X (CO/NAME_WIDTH) /* define width of screen */
#define MAX_Y (LI) /* define hight of screen */
#define STOP 256 /* codes returned by get_token */
#define READY 257
#define CURSLEFT 258
#define CURSRIGHT 259
#define CURSUP 260
#define CURSDOWN 261
#define CURSHOME 262
#define CURSEND 263
#define CURSPAGEUP 264
#define CURSPAGEDOWN 265
#define CURSMIDDLE 266
extern int term_dialog; /* do we have a terminal ? */
extern int term_clear; /* do we clear at exit ? */
extern int top_y, cur_x, cur_y; /* current position on the screen */
extern char *CL, *CM, *DL, *SO, *SE; /* for termcap */
extern int CO, LI; /* for termcap */
#define GOTOXY(x, y) fputs(tgoto(CM, (x), (y)), stdout)
#define reverse(on) fputs((on)?SO:SE, stdout)
#define clrscr() fputs(CL, stdout)
/* Should be prototypes */
extern void display();
extern int gettoken();
extern void set_cursor();
extern void term_init();
extern void term_exit();
#endif
/* Arguments for do_wait() */
#define WAIT1 "press <return> to go back to menu"
#define WAIT2 "press <return> for "
#define WAIT3 "press <return> for more ..."
#define DO_REVERSE 0x01 /* modes for do_wait() */
#define DO_DELETE 0x02
extern char *malloc();
extern char *getenv();
/* Forward declaration: */
extern void Exit();
static void man();
static void _man();
static void choose();
static int do_choose();
static int do_wait();
main(argc, argv)
int argc;
char **argv;
{
FILE *man_fd;
argv++;
argc--;
if (*argv != NULL && **argv == '/') {
(void) strcpy(ar_name, *argv); /* get archive directory */
(void) strcpy(ar_index, *argv); /* get index directory */
argv++;
argc--;
} else {
(void) strcpy(ar_name, AR_DIR); /* use default directory */
(void) strcpy(ar_index, AR_DIR);
}
(void) strcat(ar_name, AR_NAME); /* get archive name */
(void) strcat(ar_index, AR_INDEX); /* get index name */
if (*argv != NULL && isdigit(**argv)) {
(void) strcat(ar_name, *argv); /* get archive name */
(void) strcat(ar_index, *argv);
argv++;
argc--;
} else {
(void) strcat(ar_name, "1"); /* default archive */
(void) strcat(ar_index, "1");
}
man_fd = fopen(ar_name, "r"); /* open man archive */
if (man_fd == NULL) {
fprintf(stderr, "can't open %s\n", ar_name);
Exit(1);
}
read_index();
term_dialog = isatty(0) && isatty(1);
term_init();
if (*argv == NULL)
choose(man_fd);
else
man(man_fd, argv);
Exit(0);
}
void Exit(code)
int code;
{
term_exit(); /* return terminal to old status */
exit(code);
}
static void man(man_fd, man_pages)
FILE *man_fd;
char **man_pages;
{ /* copy all requested manual pages to
* standard output */
int ch;
while (1) {
_man(man_fd, *man_pages);
man_pages++;
if (*man_pages == NULL) break;
if (term_dialog) { /* wait before starting next page */
fputs(WAIT2, stdout);
if (do_wait(*man_pages, 0)) break;
fputc('\n', stdout);
}
}
}
static void _man(man_fd, man_page)
FILE *man_fd;
char *man_page;
{ /* copy the manual page to standard output */
int index_nr, ch, line_nr = -1;
/* Search entries for man_page */
for (index_nr = 0; index_nr < max_index_nr; index_nr++) {
if (strncmp(man_page, index_buf[index_nr].page_name,
NAME_SIZE) == 0)
break;
}
if (index_nr == max_index_nr) {
fprintf(stderr, "manual page for %s not available\n", man_page);
return;
}
if (fseek(man_fd, index_buf[index_nr].page_pos, 0) == -1) {
fprintf(stderr, "can't seek in manaul archive\n");
Exit(1);
}
while ((ch = fgetc(man_fd)) != '\n') { /* skip names on first line */
if (ch == EOF) break;
}
ch = fgetc(man_fd); /* display manual page */
while (ch != EOF) {
fputc(ch, stdout);
if (ch == '\n') {
ch = fgetc(man_fd);
if (ch == MAN_DELIM) break;
if (term_dialog) { /* wait after page full */
line_nr++;
if (line_nr != LI - 2) continue;
if (do_wait(WAIT3, DO_REVERSE | DO_DELETE)) break;
line_nr = 0;
}
} else
ch = fgetc(man_fd);
}
}
static void choose(man_fd)
FILE *man_fd;
{ /* driver one time chosing a page on the
* screen */
int ch, index, max_x, max_y;
if (!term_dialog) {
fprintf(stderr, "sorry, no terminal\n");
Exit(1);
}
term_clear = 1;
max_y = (max_index_nr - 1) / MAX_X; /* determine screen sizes */
max_x = max_index_nr % MAX_X;
if (max_x == 0) max_x = MAX_X;
while (1) {
index = do_choose(max_x, max_y);
if (index == STOP) break;
clrscr();
_man(man_fd, index_buf[index].page_name, 1);
(void) do_wait(WAIT1, DO_REVERSE);
};
}
static int do_choose(max_x, max_y)
int max_x, max_y;
{ /* implements the cursor movement on screen,
* returns entry number */
int token;
display(1);
set_cursor(1);
while (1) {
fflush(stdout);
token = gettoken();
if (token == READY || token == STOP) break;
set_cursor(0);
switch (token) {
case CURSLEFT:
if (cur_x > 0) cur_x--;
break;
case CURSRIGHT:
if (cur_x < MAX_X - 1) cur_x++;
break;
case CURSUP:
if (cur_y > top_y)
cur_y--;
else if (top_y > 0) {
cur_y--;
top_y--;
}
break;
case CURSDOWN:
if (cur_y < (top_y + MAX_Y - 1)) {
cur_y++;
if (cur_y > max_y) cur_y = max_y;
} else if ((top_y + MAX_Y - 1) < max_y) {
top_y++;
cur_y++;
}
break;
case CURSPAGEUP:
top_y -= MAX_Y;
if (top_y < 0) {
top_y = 0;
}
cur_y = top_y;
cur_x = 0;
break;
case CURSPAGEDOWN:
top_y += MAX_Y;
if ((top_y + MAX_Y - 1) >= max_y) {
top_y = max_y - (MAX_Y - 1);
if (top_y < 0) top_y = 0;
}
cur_y = top_y;
cur_x = 0;
break;
case CURSHOME:
top_y = 0;
cur_y = 0;
cur_x = 0;
break;
case CURSEND:
top_y = max_y - (MAX_Y - 1);
if (top_y < 0) top_y = 0;
cur_y = max_y;
cur_x = 0;
break;
case CURSMIDDLE:
clrscr(); /* redraw screen */
break;
}
if (cur_y == max_y && cur_x >= max_x) cur_x = max_x - 1;
display(token == CURSMIDDLE);
set_cursor(1);
}
if (token == STOP)
return(STOP);
else
return(cur_x + cur_y * MAX_X);
}
static int do_wait(message, mode)
char *message;
int mode;
{ /* print message and waits for a newline,
* only on terminal dialog */
int ch;
if (!term_dialog) return(0);
if (mode & DO_REVERSE) reverse(1);
fputs(message, stdout);
if (mode & DO_REVERSE) reverse(0);
fflush(stdout);
do {
ch = getchar();
} while (ch != EOF && ch != 'q' && ch != 'Q' && ch != '\n');
if ((mode & DO_DELETE) && DL) fprintf(stdout, "%s\r", DL);
if (ch == '\n') return (0); /* normal end */
return(1); /* abnormal end */
}
/* Index.c: a file to handle the index file */
/*
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <ctype.h>
#include "index.h"
*/
#define MAN_FGETC(ch, man_fd) {ch=fgetc(man_fd);man_pos++;}
#define INDEX_SIZE() (max_index_nr * sizeof(struct INDEX))
char ar_name[AR_NAME_SIZE]; /* name of man archiv